package com.msite.config
import com.github.pagehelper.PageHelper
import com.msite.config.dbrepos.FCSMyBatisRepository
import org.apache.commons.dbcp.BasicDataSource
import org.apache.ibatis.plugin.Interceptor
import org.mybatis.spring.SqlSessionFactoryBean
import org.mybatis.spring.annotation.MapperScan
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.datasource.DataSourceTransactionManager
import org.springframework.transaction.annotation.EnableTransactionManagement

import javax.sql.DataSource
/**
 * Created by tpeng on 2015/11/26.
 */
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "fcsmysql")
@EnableTransactionManagement
//@ConditionalOnExpression('${mysql.enable:false}')
@ConditionalOnExpression('true')
@MapperScan(value = ['com.msite.mapper'], sqlSessionFactoryRef = "fcssessionFactory", annotationClass = FCSMyBatisRepository.class)
class FCSMySqlConfig {

    String username;
    String password;
    String url;
    String driverClassName;

    //<!-- 连接池启动时的初始值 -->
    @Value('${initialSize:0}')
    int initialSize;
    //<!-- 最大活动连接的最大值 -->
    @Value('${maxActive:5}')
    int maxActive;
    //<!-- 最大空闲值.当经过一个高峰时间后，连接池可以慢慢将已经用不到的连接慢慢释放一部分，一直减少到maxIdle为止 -->
    @Value('${maxIdle:8}')
    int maxIdle;
    //<!-- 最小空闲值.当空闲的连接数少于阀值时，连接池就会预申请去一些连接，以免洪峰来时来不及申请 -->
    @Value('${minIdle:0}')
    int minIdle;
    //最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常,如果设置为-1表示无限等待
    @Value('${maxWait:1000}')
    int maxWait;
    @Value('${validationQuery:""}')
    String validationQuery;
    //标记是否删除泄露的连接,如果他们超过了removeAbandonedTimout的限制.
    @Value('${removeAbandoned:true}')
    boolean removeAbandoned;
    @Value('${removeAbandonedTimeout:300}')
    int removeAbandonedTimeout;
    //标记当Statement或连接被泄露时是否打印程序的stack traces日志。
    @Value('${logAbandoned:true}')
    boolean logAbandoned;

    /**
     * Java数据库连接有“8小时问题”，所以destroy-method="close"一定要加上。
     * “8小时问题”是指一个连接空闲8小时数据库会自动关闭，而数据源并不知道。
     * @return
     */
    DataSource getFcsBasicDataSource() {
        def dataSource = new BasicDataSource(
                username: this.username,
                password: this.password,
                url: this.url,
                driverClassName: this.driverClassName,
                initialSize: this.initialSize,
                maxActive: this.maxActive,
                maxIdle: this.maxIdle,
                minIdle: this.minIdle,
                maxWait: this.maxWait,
                validationQuery: this.validationQuery,
                removeAbandoned: this.removeAbandoned,
                removeAbandonedTimeout: this.removeAbandonedTimeout,
                logAbandoned: this.logAbandoned
        );
        Runtime.getRuntime().addShutdownHook(new BigDataSourceCloseThread(dataSource));
        dataSource
    }

    private static class BigDataSourceCloseThread extends  Thread{
        private BasicDataSource dataSource;
        BigDataSourceCloseThread(BasicDataSource dataSource){
            this.dataSource = dataSource;
        }
        @Override
        public void run() {
            if(this.dataSource != null){
                System.out.println("====================================");
                System.out.println("big datasource : close");
                System.out.println("====================================");
                this.dataSource.close();
            }
        }
    }

    public JdbcTemplate getfcsJdbcTemplate() {
        new JdbcTemplate(dataSource: getFcsBasicDataSource());
    }

    @Bean(name = "fcstransactionManager")
    public DataSourceTransactionManager getDataSourceTransactionManager() {
        new DataSourceTransactionManager(dataSource: getFcsBasicDataSource());
    }

    @Bean(name = "fcssessionFactory")
    SqlSessionFactoryBean getFcsSqlSessionFactoryBean(){
        def sessionFactory = new SqlSessionFactoryBean(
                dataSource: getFcsBasicDataSource()
        );
        sessionFactory.setPlugins([fcspageHelper()] as Interceptor[]);
        sessionFactory
    }

    PageHelper fcspageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("dialect", "mysql");
        p.setProperty("offsetAsPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true");
        p.setProperty("pageSizeZero", "true");
        p.setProperty("reasonable", "true");
        p.setProperty("params", "pageNum=start;pageSize=limit;");
        pageHelper.setProperties(p);
        return pageHelper;
    }

}
